package cn.ichiva.wall_street.service;

import cn.ichiva.common.io.IOHelper;
import cn.ichiva.dl.tushare.analy.impl.Record;
import cn.ichiva.dl.tushare.analy.impl.Trade;
import cn.ichiva.wall_street.api.vo.StockVO;
import cn.ichiva.wall_street.domian.PredictRes;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by game group on 2020/11/27.
 */
@Slf4j
@Service
public class AgentService {

    @Value("${dataDir:./data}")
    String dataDir;

    /**
     * 智能体名称集合
     * @return
     */
    public Collection<StockVO> list() {
        HashMap<String,String> map = new HashMap<>();
        try {
            Files.readAllLines(new File(dataDir, "remark.txt").toPath())
                    .forEach(e -> {
                        String[] arr = e.split("=");
                        map.put(arr[0],arr[1]);
                    });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return Arrays.stream(new File(dataDir).listFiles())
                .filter(e -> {
                    String name = e.getName();
                    String suffix = name.substring(name.length() - 2);
                    return "sz".equalsIgnoreCase(suffix) || "sh".equalsIgnoreCase(suffix);
                })
                .map(e -> new StockVO(e.getName(),map.get(e.getName())))
                .collect(Collectors.toList());
    }


    public PredictRes predictRes(String ts_code){
        File file = new File(dataDir, ts_code);
        try {
            File optFile = new File(file, "opt.txt");
            byte[] bytes = IOHelper.read(optFile);
            String[] arr = new String(bytes).split("=");
            PredictRes res = new PredictRes();
            res.setDay(arr[0]);
            res.setTs_code(ts_code);
            res.setRes(Integer.parseInt(arr[1]));
            res.setTime(optFile.lastModified());
            return res;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取操作记录
     * @param ts_code
     * @param skip
     * @return
     */
    public List<String> getOperationRecord(String ts_code, int skip,int size) {
        try {
            Trade trade = (Trade) IOHelper.readObject(new File(new File(dataDir, ts_code), "trade.obj"));
            LinkedList<Record> tradeRecord = trade.getTradeRecord();
            Collections.reverse(tradeRecord);
            return tradeRecord.stream()
                    .skip(skip)
                    .limit(size)
                    .map(e -> JSON.toJSONString(e)).collect(Collectors.toList());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 订阅
     * @param ts_code
     * @param mail
     * @return
     */
    public boolean subscribe(String ts_code, String mail) {
        if(null == mail || mail.length() == 0) return false;
        File file = new File(new File(dataDir, ts_code), "subscribe.txt");

        Set<String> mails = null;
        try {
            mails = getMails(file);
            file.delete();
        } catch (IOException e) {
            log.warn("文件读取异常",e);
            return false;
        }

        try(PrintWriter writer = new PrintWriter(new FileWriter(file,true))){
            if(mail.charAt(0) == '-') mails.remove(mail.substring(1));
            else mails.add(mail);

            mails.forEach(writer::println);
            return true;
        } catch (IOException e) {
            log.warn("文件写入异常",e);
            return false;
        }
    }

    private Set<String> getMails(File file) throws IOException {
        Set<String> set = new HashSet<>();
        Files.readAllLines(file.toPath()).forEach(e -> {
            if(e.charAt(0) == '-') set.remove(e.substring(1));
            else set.add(e);
        });
        return set;
    }
}
